#include "hal_data.h"
#include "board.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

#define LINE_CODING_LENGTH (0x07U)

usb_status_t usb_event;
usb_setup_t usb_setup;

uint8_t g_usb_module_number = 0x00;
usb_class_t g_usb_class_type = 0x00;

static char send_str[12] = { "LED on\n\r"};
static volatile uint8_t s1_pressed = false;
static uint8_t led_level = BSP_IO_LEVEL_HIGH;

static volatile uint8_t g_transfer_complete = false;
uint32_t SPI_Read_ID(void);
void I2C_example (void);


/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
    static usb_pcdc_linecoding_t g_line_coding;
    extern bsp_leds_t g_bsp_leds;
    uint32_t flashID = 0;


    g_external_irq015.p_api->open (g_external_irq015.p_ctrl,g_external_irq015.p_cfg);
    g_external_irq015.p_api->enable (g_external_irq015.p_ctrl);

#if 0
    R_USB_Open (&g_basic0_ctrl, &g_basic0_cfg);
    R_USB_ClassTypeGet (&g_basic0_ctrl, &g_usb_class_type);
    R_USB_ModuleNumberGet (&g_basic0_ctrl, &g_usb_module_number);
#endif

    g_ioport.p_api->pinWrite (&g_ioport_ctrl, g_bsp_leds.p_leds[BSP_LED_LED1], BSP_IO_LEVEL_LOW);
    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
    g_ioport.p_api->pinWrite (&g_ioport_ctrl, g_bsp_leds.p_leds[BSP_LED_LED1], BSP_IO_LEVEL_HIGH);
    g_ioport.p_api->pinWrite (&g_ioport_ctrl, g_bsp_leds.p_leds[BSP_LED_LED2], BSP_IO_LEVEL_LOW);
    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
    g_ioport.p_api->pinWrite (&g_ioport_ctrl, g_bsp_leds.p_leds[BSP_LED_LED2], BSP_IO_LEVEL_HIGH);
    g_ioport.p_api->pinWrite (&g_ioport_ctrl, g_bsp_leds.p_leds[BSP_LED_LED3], BSP_IO_LEVEL_LOW);

    g_ioport.p_api->pinWrite (&g_ioport_ctrl, F_nCS, BSP_IO_LEVEL_LOW);
    flashID = SPI_Read_ID();
    //I2C_example();

    while(1)
    {
#if 0
        R_USB_EventGet (&g_basic0_ctrl, &usb_event);
        if (usb_event == USB_STATUS_REQUEST)
        {
            R_USB_SetupGet (&g_basic0_ctrl, &usb_setup);
            if (USB_PCDC_SET_LINE_CODING == (usb_setup.request_type & USB_BREQUEST))
            {
                R_USB_PeriControlDataGet (&g_basic0_ctrl,(uint8_t*) &g_line_coding, LINE_CODING_LENGTH);
            }
            else if (USB_PCDC_GET_LINE_CODING == (usb_setup.request_type & USB_BREQUEST))
            {
                R_USB_PeriControlDataSet (&g_basic0_ctrl,(uint8_t*) &g_line_coding, LINE_CODING_LENGTH);
            }
            else if (USB_PCDC_SET_CONTROL_LINE_STATE == (usb_setup.request_type & USB_BREQUEST))
            {
                R_USB_PeriControlStatusSet (&g_basic0_ctrl, USB_SETUP_STATUS_ACK);
            }
            else
            {
            }
        }

        if (s1_pressed == true)
        {
            s1_pressed = false;
            if (led_level == BSP_IO_LEVEL_HIGH)
            {
                strcpy (send_str, "LED off\n\r");
                led_level = BSP_IO_LEVEL_LOW;
            }
            else
            {
                strcpy (send_str, "LED on\n\r");
                led_level = BSP_IO_LEVEL_HIGH;
            }
        }
#endif
    }
#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}

#if BSP_TZ_SECURE_BUILD

BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
#endif

void external_irq015_callback(external_irq_callback_args_t *p_args)
{
    /* Not currently using p_args */
    FSP_PARAMETER_NOT_USED(p_args);

    extern bsp_leds_t g_bsp_leds;
    bsp_leds_t Leds = g_bsp_leds;

    s1_pressed = true;
    g_ioport.p_api->pinWrite (&g_ioport_ctrl, Leds.p_leds[BSP_LED_LED2], led_level);

    R_USB_Write (&g_basic0_ctrl, (uint8_t*) send_str, ((uint32_t) strlen (send_str)), (uint8_t) g_usb_class_type);
}

void sci_spi_callback(spi_callback_args_t *p_args)
{
    if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
    {
      g_transfer_complete = true;
    }
}

void spi_callback(spi_callback_args_t *p_args)
{
    if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
    {
        g_transfer_complete = true;
    }
}



#define DUMMY             0x00
#define READ_JEDEC_ID     0x9f
#define FLASH_DUMMY_BYTE  0x5A

uint32_t SPI_Read_ID(void)
{
    uint32_t flash_id;
    fsp_err_t err = FSP_SUCCESS;
    uint8_t f_cmd = READ_JEDEC_ID;

    //uint8_t f_data = 0;
    uint8_t f_cmd2[3] = {FLASH_DUMMY_BYTE,FLASH_DUMMY_BYTE,FLASH_DUMMY_BYTE};
    uint8_t rdata[3] = {0};
    //err = R_SCI_SPI_Open(&g_spi0_ctrl, &g_spi0_cfg);
    err = R_SPI_Open(&g_spi1_ctrl, &g_spi1_cfg);
    assert(FSP_SUCCESS == err);

    g_transfer_complete = false;
    err = R_SPI_Write(&g_spi1_ctrl,&f_cmd,1,SPI_BIT_WIDTH_8_BITS);
    assert(FSP_SUCCESS == err);
    while (false == g_transfer_complete){;}

    //g_transfer_complete = false;
    //err = R_SPI_Write(&g_spi1_ctrl,&f_cmd2,3,SPI_BIT_WIDTH_8_BITS);
    //assert(FSP_SUCCESS == err);
    //while (false == g_transfer_complete){;}

    g_transfer_complete = false;
    err = R_SPI_WriteRead(&g_spi1_ctrl, f_cmd2, rdata, 3, SPI_BIT_WIDTH_8_BITS);
    assert(FSP_SUCCESS == err);
    while (false == g_transfer_complete){;}

    //err = R_SPI_Read(&g_spi1_ctrl,rdata,3,SPI_BIT_WIDTH_8_BITS);
    //err = R_SPI_WriteRead(&g_spi1_ctrl, &f_cmd, &rdata[0], 1, SPI_BIT_WIDTH_8_BITS);
    //assert(FSP_SUCCESS == err);
    //while (false == g_transfer_complete){;}

    //g_transfer_complete = false;
    //err = R_SPI_WriteRead(&g_spi1_ctrl, &f_cmd, &rdata[1], 1, SPI_BIT_WIDTH_8_BITS);
    //assert(FSP_SUCCESS == err);
    //while (false == g_transfer_complete){;}

    //g_transfer_complete = false;
    //err = R_SPI_WriteRead(&g_spi1_ctrl, &f_cmd, &rdata[2], 1, SPI_BIT_WIDTH_8_BITS);
    //assert(FSP_SUCCESS == err);
    //while (false == g_transfer_complete){;}

    flash_id = rdata[0];
    flash_id <<= 8;
    flash_id |= rdata[1];
    flash_id <<= 8;
    flash_id |= rdata[2];

    return flash_id;
}

void I2C_example (void)
{
    fsp_err_t err;
    uint8_t tx_buffer[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    uint8_t rx_buffer[16]={0};
    uint8_t EEaddr[2] = {0x00,0x01};
    static uint8_t dataT = 0x5e;
    uint8_t dataR = 0;

    /* Initialize the IIC module */
    err = R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);

    /* Send data to I2C slave */
    //g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
    err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, EEaddr, 2, false);
    assert(FSP_SUCCESS == err);
    err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, &dataT, 1, false);
    assert(FSP_SUCCESS == err);

    R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MICROSECONDS);

    /* Read data back from the I2C slave */
    err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, EEaddr, 2, true);
    assert(FSP_SUCCESS == err);
    err = R_IIC_MASTER_Read(&g_i2c_master0_ctrl, &dataR, 1, false);
    assert(FSP_SUCCESS == err);

    R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MICROSECONDS);
    /* Verify the read data */
    if (0U != memcmp(tx_buffer, rx_buffer, 16))
    {

    }
}




